﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace VehicleMaintenance.Comm
{
	public class Print
	{
		public static void DrawControl(Control ctl, Point ptOffset, Graphics g)
		{
			// Cycle through each control on the form and paint it on the graphics object
			foreach (Control c in ctl.Controls)
			{
				// Skip invisible controls
				if (!c.Visible)
					continue;

				// Calculate the location offset for the control - this offset is
				// relative to the original offset passed in
				Point p = new Point(c.Left, c.Top);
				p.Offset(ptOffset.X, ptOffset.Y);

				// Draw the control
				if (c is TableLayoutPanel)
					DrawTableLayoutPanel((TableLayoutPanel)c, p, g);
				else if (c is GroupBox)
					DrawGroupBox((GroupBox)c, p, g);
				else if (c is Button)
					DrawButton((Button)c, p, g);
				else if (c is TextBox)
					DrawTextBox((TextBox)c, p, g);
				else if (c is CheckBox)
					DrawCheckBox((CheckBox)c, p, g);
				else if (c is Label)
					DrawLabel((Label)c, p, g);
				else if (c is ComboBox)
					DrawComboBox((ComboBox)c, p, g);
				else if (c is RadioButton)
					DrawRadioButton((RadioButton)c, p, g);
				//else
				//return;

				// Draw the controls within this control
				DrawControl(c, p, g);
			}
		}

		public static void DrawTableLayoutPanel(TableLayoutPanel grp, Point p, Graphics g)
		{
			int iBorder = 1;
			g.FillRectangle(new SolidBrush(grp.BackColor),
				p.X - 1,
				p.Y - 1,
				grp.Width,
				grp.Height - 2);
			ControlPaint.DrawBorder(g,
				new Rectangle(p.X, p.Y, grp.Width, grp.Height),
				Color.Black,
				iBorder,
				ButtonBorderStyle.Solid,
				Color.Black,
				iBorder,
				ButtonBorderStyle.Solid,
				Color.Black,
				iBorder,
				ButtonBorderStyle.Solid,
				Color.Black,
				iBorder,
				ButtonBorderStyle.Solid);


			//Point[] pt = new Point[(grp.ColumnCount - 1) * (grp.RowCount - 1) * 2];
			int curX = 0;
			int curY = 0;
			for (int i = 0; i < grp.RowCount - 1; i++)
			{
				//int iFontHeight = (int)g.MeasureString(grp.Controls[i].Text, grp.Controls[i].Font).Height;

				//画横线
				Point pt1 = new Point();
				Point pt2 = new Point();
				switch (grp.RowStyles[i].SizeType)
				{
					case SizeType.Absolute:
						{
							pt1.X = 0;
							pt1.Y = Convert.ToInt32(grp.RowStyles[i].Height) + curY;
							pt1.Offset(p);

							pt2.X = grp.Width - iBorder;
							pt2.Y = Convert.ToInt32(grp.RowStyles[i].Height) + curY;
							pt2.Offset(p);

							curY += Convert.ToInt32(grp.RowStyles[i].Height);
							break;
						}
					case SizeType.Percent:
						{
							pt1.X = 0;
							pt1.Y = Convert.ToInt32(grp.RowStyles[i].Height * grp.Height / 100) + curY;
							pt1.Offset(p);

							pt2.X = grp.Width - iBorder;
							pt2.Y = Convert.ToInt32(grp.RowStyles[i].Height * grp.Height / 100) + curY;
							pt2.Offset(p);

							curY += Convert.ToInt32(grp.RowStyles[i].Height * grp.Height / 100);
							break;
						}
				}


				g.DrawLine(new Pen(new SolidBrush(grp.ForeColor)), pt1, pt2);
			}
			for (int i = 0; i < grp.ColumnCount - 1; i++)
			{
				//画竖线
				Point pt1 = new Point();
				Point pt2 = new Point();
				switch (grp.ColumnStyles[i].SizeType)
				{
					case SizeType.Absolute:
						{
							pt1.X = Convert.ToInt32(grp.ColumnStyles[i].Width) + curX;
							pt1.Y = 0;
							pt1.Offset(p);

							pt2.X = Convert.ToInt32(grp.ColumnStyles[i].Width) + curX;
							pt2.Y = grp.Height - iBorder;
							pt2.Offset(p);

							curX += Convert.ToInt32(grp.ColumnStyles[i].Width);
							break;
						}
					case SizeType.Percent:
						{
							pt1.X = Convert.ToInt32(grp.ColumnStyles[i].Width * grp.Width / 100) + curX;
							pt1.Y = 0;
							pt1.Offset(p);

							pt2.X = Convert.ToInt32(grp.ColumnStyles[i].Width * grp.Width / 100) + curX;
							pt2.Y = grp.Height - iBorder;
							pt2.Offset(p);

							curX += Convert.ToInt32(grp.ColumnStyles[i].Width * grp.Width / 100);
							break;
						}
				}

				g.DrawLine(new Pen(new SolidBrush(grp.ForeColor)), pt1, pt2);
			}

		}

		/// <summary>
		/// Draws the specified GroupBox on the specified graphics object at the
		/// specified location.
		/// </summary>
		public static void DrawGroupBox(GroupBox grp, Point p, Graphics g)
		{
			// Control's BackColor
			g.FillRectangle(new SolidBrush(grp.BackColor),
				p.X,
				p.Y,
				grp.Width,
				grp.Height);

			// Draw a rectangle leaving space for the heading
			int iFontHeight = (int)g.MeasureString(grp.Text, grp.Font).Height;
			Point[] pt = new Point[6];
			pt[0].X = p.X + 10;
			pt[0].Y = p.Y + (iFontHeight / 2);
			pt[1].X = p.X;
			pt[1].Y = p.Y + (iFontHeight / 2);
			pt[2].X = p.X;
			pt[2].Y = p.Y + grp.Height;
			pt[3].X = p.X + grp.Width;
			pt[3].Y = p.Y + grp.Height;
			pt[4].X = p.X + grp.Width;
			pt[4].Y = p.Y + (iFontHeight / 2);
			pt[5].X = p.X + (int)g.MeasureString(grp.Text, grp.Font).Width + 10 + 2;
			if (pt[5].X < p.X)
				pt[5].X = p.X;
			pt[5].Y = p.Y + (iFontHeight / 2);
			g.DrawLines(new Pen(new SolidBrush(grp.ForeColor), 1), pt);

			// GroupBox's text
			g.DrawString(grp.Text,
				grp.Font,
				new SolidBrush(grp.ForeColor),
				p.X + 10 + 2,
				p.Y,
				new StringFormat());
		}

		/// <summary>
		/// Draws the specified TextBox on the specified graphics object at the
		/// specified location.
		/// </summary>
		public static void DrawTextBox(TextBox txt, Point p, Graphics g)
		{
			int iBorder = 2;

			// Draw the TextBox border
			//ControlPaint.DrawBorder(g,
			//    new Rectangle(p.X, p.Y, txt.Width, txt.Height),
			//    SystemColors.Control,
			//    iBorder,
			//    ButtonBorderStyle.Inset,
			//    SystemColors.Control,
			//    iBorder,
			//    ButtonBorderStyle.Inset,
			//    SystemColors.Control,
			//    iBorder,
			//    ButtonBorderStyle.Inset,
			//    SystemColors.Control,
			//    iBorder,
			//    ButtonBorderStyle.Inset);

			//// Control's BackColor
			//g.FillRectangle(new SolidBrush(txt.BackColor),
			//    p.X + iBorder,
			//    p.Y + iBorder,
			//    txt.Width - 4,
			//    txt.Height - 5);

			// TextBox's text left justified & centered vertically
			g.DrawString(txt.Text,
				txt.Font,
				new SolidBrush(txt.ForeColor),
				p.X + iBorder,
				p.Y + ((txt.Height - 2) / 2) - (g.MeasureString(txt.Text, txt.Font).Height / 2));
		}

		/// <summary>
		/// Draws the specified ComboBox on the specified graphics object at the
		/// specified location.
		/// </summary>
		/// <remarks>
		/// The size of the Combo button itself is hard-coded here and was determined by
		/// using a graphics program.
		/// </remarks>
		public static void DrawComboBox(ComboBox cbo, Point p, Graphics g)
		{
			int iBorder = 2;

			// Draw the TextBox border
			ControlPaint.DrawBorder(g,
				new Rectangle(p.X, p.Y, cbo.Width, cbo.Height),
				SystemColors.Control,
				iBorder,
				ButtonBorderStyle.Inset,
				SystemColors.Control,
				iBorder,
				ButtonBorderStyle.Inset,
				SystemColors.Control,
				iBorder,
				ButtonBorderStyle.Inset,
				SystemColors.Control,
				iBorder,
				ButtonBorderStyle.Inset);

			// Control's BackColor
			g.FillRectangle(new SolidBrush(cbo.BackColor),
				p.X + iBorder,
				p.Y + iBorder,
				cbo.Width - 4,
				cbo.Height - 4);

			// ComboBox's text left justified & centered vertically
			g.DrawString(cbo.Text,
				cbo.Font,
				new SolidBrush(cbo.ForeColor),
				p.X + iBorder,
				p.Y + (cbo.Height / 2) - (g.MeasureString(cbo.Text, cbo.Font).Height / 2));

			// ComboBox's drop down arrow button thingy
			ControlPaint.DrawComboButton(g,
				p.X + cbo.Width - 16 - iBorder,
				p.Y + (cbo.Height / 2) - (16 / 2),
				16,
				17,
				ButtonState.Normal);
		}

		/// <summary>
		/// Draws the specified Label on the specified graphics object at the
		/// specified location.
		/// </summary>
		public static void DrawLabel(Label lbl, Point p, Graphics g)
		{
			int iBorder = 2;
			// Control's BackColor
			g.FillRectangle(new SolidBrush(lbl.BackColor),
				p.X,
				p.Y - 1,
				lbl.Width - 2,
				lbl.Height - 2);

			// Label's text centered on both axis
			float iX = p.X;
			if (lbl.TextAlign == ContentAlignment.MiddleCenter)//居中显示
			{
				iX = p.X + (lbl.Width / 2) - (g.MeasureString(lbl.Text, lbl.Font).Width / 2);
			}
			g.DrawString(
				lbl.Text,
				lbl.Font,
				new SolidBrush(lbl.ForeColor),
				iX,//+ (lbl.Width / 2) - (g.MeasureString(lbl.Text, lbl.Font).Width / 2),
				p.Y + (lbl.Height / 2) - (g.MeasureString(lbl.Text, lbl.Font).Height / 2));
		}

		/// <summary>
		/// Draws the specified Button on the specified graphics object at the
		/// specified location.
		/// </summary>
		public static void DrawButton(Button btn, Point p, Graphics g)
		{
			ControlPaint.DrawButton(g, p.X, p.Y, btn.Width, btn.Height, ButtonState.Normal);

			// Button's text centered on both axis
			g.DrawString(
				btn.Text,
				btn.Font,
				new SolidBrush(btn.ForeColor),
				p.X + (btn.Width / 2) - (g.MeasureString(btn.Text, btn.Font).Width / 2),
				p.Y + (btn.Height / 2) - (g.MeasureString(btn.Text, btn.Font).Height / 2));
		}

		/// <summary>
		/// Draws the specified CheckBox on the specified graphics object at the
		/// specified location.
		/// </summary>
		/// <remarks>
		/// The size of the CheckBox itself is hard-coded here and was determined by
		/// using a graphics program.
		/// </remarks>
		public static void DrawCheckBox(CheckBox chk, Point p, Graphics g)
		{
			// Set up the size of a CheckBox
			Rectangle rCheckBox = new Rectangle(p.X, p.Y, 13, 13);

			ControlPaint.DrawCheckBox(g, p.X,
				p.Y + (chk.Height / 2) - (rCheckBox.Height / 2),
				rCheckBox.Width,
				rCheckBox.Height,
				(chk.Checked ? ButtonState.Checked : ButtonState.Normal));

			// CheckBox's text left justified & centered vertically
			g.DrawString(chk.Text,
				chk.Font,
				new SolidBrush(chk.ForeColor),
				rCheckBox.Right + 1,
				p.Y + (chk.Height / 2) - (g.MeasureString(chk.Text, chk.Font).Height / 2));
		}

		/// <summary>
		/// Draws the specified RadioButton on the specified graphics object at the
		/// specified location.
		/// </summary>
		/// <remarks>
		/// The size of the RadioButton itself is hard-coded here and was determined by
		/// using a graphics program.
		/// </remarks>
		public static void DrawRadioButton(RadioButton rdo, Point p, Graphics g)
		{
			// Setup the size of a RadioButton
			Rectangle rRadioButton = new Rectangle(p.X, p.Y, 12, 12);

			ControlPaint.DrawRadioButton(g, p.X,
				p.Y + (rdo.Height / 2) - (rRadioButton.Height / 2),
				rRadioButton.Width,
				rRadioButton.Height,
				(rdo.Checked ? ButtonState.Checked : ButtonState.Normal));

			// RadioButton's text left justified & centered vertically
			g.DrawString(rdo.Text,
				rdo.Font,
				new SolidBrush(rdo.ForeColor),
				rRadioButton.Right + 1,
				p.Y + (rdo.Height / 2) - (g.MeasureString(rdo.Text, rdo.Font).Height / 2));
		}

		/// <summary>
		/// Calculates pagination based on the contents of the form for the specified margins.
		/// </summary>
		/// <remarks>
		/// Each point represents the upper-left corner to where the printing rectangle
		/// will be set
		/// </remarks>
		public static Point[] GeneratePrintingOffsets(Form form, Rectangle rMargins)
		{
			// Setup the array of Points
			int x = (int)Math.Ceiling((double)(form.Width) / (double)(rMargins.Width));
			int y = (int)Math.Ceiling((double)(form.Height) / (double)(rMargins.Height));
			Point[] arrPoint = new Point[x * y];

			// Fill the array
			for (int i = 0; i < y; i++)
				for (int j = 0; j < x; j++)
					arrPoint[i * x + j] = new Point(j * rMargins.Width, i * rMargins.Height);

			return arrPoint;
		}
	}
}
